package com.bsj.power.tool.config.websocket;

import cn.hutool.core.io.file.FileReader;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.yeauty.annotation.OnClose;
import org.yeauty.annotation.OnMessage;
import org.yeauty.annotation.OnOpen;
import org.yeauty.annotation.ServerEndpoint;
import org.yeauty.pojo.Session;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.IntStream;

/**
 * @author yinhao
 * @version 1.0
 * @description 测试websocket服务端
 * @date 2024/7/17
 */
@ServerEndpoint(port = "28080", path = "/tool")
@Component
@Slf4j
public class TestWebSocketServer {

    @Value("${file.pos}")
    private String posUrl;

    static Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    static ExecutorService executorService = null;
    static List<Future> futureList = null;

    static Thread thread = null;
    static List<Thread> threads = null;

    /**
     * 消息发送
     *
     * @param o
     */
    public void sendData(Object o) {
        sessionMap.forEach((key, value) -> {
            value.sendText(JSONObject.toJSONString(o));
        });
    }

    /**
     * 建立连接时执行的操作
     *
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) {
        sessionMap.put(session.id().asShortText(), session);
    }

//    /**
//     * 收到客户端消息时执行的操作
//     *
//     * @param text 接受到客户端的消息
//     * @return 返回给客户端的消息
//     */
//    @OnMessage
//    public void onMessage(Session session, String text) throws Exception {
//        log.info("收到一条新消息: " + text);
//        session.sendText("okk");
//        if (!text.startsWith("run") && !text.startsWith("stop")) {
//            return;
//        }
//        String[] split = text.split(":");
//        switch (split[0]) {
//            case "run":
//                //run:122:321321
//                int anInt = Integer.parseInt(split[1]);
//                // 使用
//                File file = new File(posUrl);
//                FileReader reader = new FileReader(file);
//                String readString = reader.readString();
//                if (sessionMap.isEmpty()) {
//                    break;
//                }
//                if (thread != null) {
//                    thread.stop();
//                }
//                JSONArray parseArray = JSON.parseArray(readString);
//                thread = new Thread(new Runnable() {
//                    @Override
//                    public void run() {
//                        while (true) {
//                            for (int j = 0; j < parseArray.size(); j++) {
//                                JSONObject dataJsonObject = parseArray.getJSONObject(j);
//                                String sn = dataJsonObject.getString("sn");
//                                JSONArray jsonArray = dataJsonObject.getJSONArray("pos");
//                                String testData = "{\"id\":2,\"name\":\"T2\",\"sn\":\"12360317305344412205\",\"type\":2,\"data\":{\"name\":\"T2\",\"sn\":\"12360317305344412205\",\"pos\":[-11.397556112216488,-10.702471829020258,-1.437753420949302],\"time\":1717753195151,\"sourceId\":0,\"noiseRadius\":0.4003624,\"mapId\":1,\"rxAnchorId\":105,\"rxAnchorSn\":\"5202027035587379238\",\"rxRssi\":-46.84048,\"vel\":[-0.0014880153202020427,-0.0001049110877793672,-0.0006400506818056755],\"posVar\":[0.138574442963652,0.019282158065526883,0.00022574845972017513],\"velVar\":[0.000006928722148182719,9.641079032764216e-7,4.514969194405162e-8],\"solveTimeSec\":0.00003528}}";
//                                JSONObject obj = JSONObject.parseObject(testData);
//                                obj.put("sn", sn);
//                                JSONObject objData = obj.getJSONObject("data");
//                                objData.put("sn", sn);
//                                JSONObject result = new JSONObject();
//                                result.put("type", 14);
//                                // 正序遍历
//                                IntStream.range(0, jsonArray.size())
//                                        .forEach(i -> {
//                                            JSONObject jsonObject = jsonArray.getJSONObject(i);
//                                            Double x = jsonObject.getDouble("x");
//                                            Double y = jsonObject.getDouble("y");
//                                            Double z = jsonObject.getDouble("z");
//                                            objData.put("pos", new double[]{x, y, z});
//                                            objData.put("time", System.currentTimeMillis());
//                                            obj.put("data", objData);
//                                            result.put("data", obj.toJSONString());
//                                            sendData(result);
//                                            try {
//                                                Thread.sleep(anInt);
//                                            } catch (InterruptedException e) {
//                                                e.printStackTrace();
//                                            }
//                                        });
//                                // 倒序遍历
//                                IntStream.range(0, jsonArray.size())
//                                        .map(i -> jsonArray.size() - 1 - i)
//                                        .forEach(i -> {
//                                            JSONObject jsonObject = jsonArray.getJSONObject(i);
//                                            Double x = jsonObject.getDouble("x");
//                                            Double y = jsonObject.getDouble("y");
//                                            Double z = jsonObject.getDouble("z");
//                                            objData.put("pos", new double[]{x, y, z});
//                                            objData.put("time", System.currentTimeMillis());
//                                            obj.put("data", objData);
//                                            result.put("data", obj.toJSONString());
//                                            sendData(result);
//                                            try {
//                                                Thread.sleep(anInt);
//                                            } catch (InterruptedException e) {
//                                                e.printStackTrace();
//                                            }
//                                        });
//                            }
//                        }
//                    }
//                });
//                thread.start();
//                break;
//            case "stop":
//                thread.stop();
//                break;
//            default:
//                break;
//        }
//    }

    /**
     * 收到客户端消息时执行的操作
     *
     * @param text 接受到客户端的消息
     * @return 返回给客户端的消息
     */
    @OnMessage
    public void onMessage(Session session, String text) throws Exception {
        log.info("收到一条新消息: " + text);
        session.sendText("okk");
        if (!text.startsWith("run") && !text.startsWith("stop")) {
            return;
        }
        String[] split = text.split(":");
        switch (split[0]) {
            case "run":
                //run:122:321321
                int anInt = Integer.parseInt(split[1]);
                // 使用
                File file = new File(posUrl);
                FileReader reader = new FileReader(file);
                String readString = reader.readString();
                if (sessionMap.isEmpty()) {
                    break;
                }
                if (executorService != null) {
                    executorService.shutdown();
                }
                JSONArray parseArray = JSON.parseArray(readString);
                int size = parseArray.size();
                executorService = Executors.newFixedThreadPool(size);
                for (int i = 0; i < size; i++) {
                    int finalI = i;
                    Runnable task = () -> {
                        subPos(parseArray.getJSONObject(finalI), anInt);
                    };
                    Future submit = executorService.submit(task);
                    futureList = new ArrayList<>();
                    futureList.add(submit);
                }
                break;
            case "stop":
                futureList.stream().forEach(future -> {
                    future.cancel(true);
                });
                executorService.shutdownNow();
                break;
            default:
                break;
        }
    }

    private void subPos(JSONObject dataJsonObject, Integer anInt) {
        while (true) {
            if (Thread.currentThread().isInterrupted()) {
                break;
            }
            String sn = dataJsonObject.getString("sn");
            JSONArray jsonArray = dataJsonObject.getJSONArray("pos");
            String testData = "{\"id\":2,\"name\":\"T2\",\"sn\":\"12360317305344412205\",\"type\":2,\"data\":{\"name\":\"T2\",\"sn\":\"12360317305344412205\",\"pos\":[-11.397556112216488,-10.702471829020258,-1.437753420949302],\"time\":1717753195151,\"sourceId\":0,\"noiseRadius\":0.4003624,\"mapId\":1,\"rxAnchorId\":105,\"rxAnchorSn\":\"5202027035587379238\",\"rxRssi\":-46.84048,\"vel\":[-0.0014880153202020427,-0.0001049110877793672,-0.0006400506818056755],\"posVar\":[0.138574442963652,0.019282158065526883,0.00022574845972017513],\"velVar\":[0.000006928722148182719,9.641079032764216e-7,4.514969194405162e-8],\"solveTimeSec\":0.00003528}}";
            JSONObject obj = JSONObject.parseObject(testData);
            obj.put("sn", sn);
            JSONObject objData = obj.getJSONObject("data");
            objData.put("sn", sn);
            JSONObject result = new JSONObject();
            result.put("type", 14);
            // 正序遍历
            IntStream.range(0, jsonArray.size())
                    .forEach(i -> {
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        Double x = jsonObject.getDouble("x");
                        Double y = jsonObject.getDouble("y");
                        Double z = jsonObject.getDouble("z");
                        Integer mapId = jsonObject.getInteger("mapId");
                        objData.put("pos", new double[]{x, y, z});
                        objData.put("time", System.currentTimeMillis());
                        objData.put("mapId", mapId);
                        obj.put("data", objData);
                        result.put("data", obj.toJSONString());
                        sendData(result);
                        try {
                            Thread.sleep(anInt);
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                            e.printStackTrace();
                        }
                    });
            // 倒序遍历
            IntStream.range(0, jsonArray.size())
                    .map(i -> jsonArray.size() - 1 - i)
                    .forEach(i -> {
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        Double x = jsonObject.getDouble("x");
                        Double y = jsonObject.getDouble("y");
                        Double z = jsonObject.getDouble("z");
                        Integer mapId = jsonObject.getInteger("mapId");
                        objData.put("pos", new double[]{x, y, z});
                        objData.put("time", System.currentTimeMillis());
                        objData.put("mapId", mapId);
                        obj.put("data", objData);
                        result.put("data", obj.toJSONString());
                        sendData(result);
                        try {
                            Thread.sleep(anInt);
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                            e.printStackTrace();
                        }
                    });
        }
    }

    /**
     * 连接关闭时执行的操作
     *
     * @param session
     */
    @OnClose
    public void onClose(Session session) {
        log.info("websocket is close");
        sessionMap.remove(session.id().asShortText());
        if (sessionMap.isEmpty() && thread != null) {
            thread.stop();
        }
    }
}
